package flyshoes.routes;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {
    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter routeDefinitionWriter;
    private final String dateId = "gateway.json";
    private final String group = "DEFAULT_GROUP";
    private final Set<String> routeIds = new HashSet<>();

    @PostConstruct
    public void initRouteListener() throws NacosException {
        String routeInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dateId, group, 5000, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }

            @Override
            public void receiveConfigInfo(String routeInfo) {
                updateRouteInfo(routeInfo);//监听配置，更新到路由表中
            }
        });
        updateRouteInfo(routeInfo);//第一次读取配置，也需要进行更新到路由表中
    }

    public void updateRouteInfo(String routeInfo) {
        log.debug("路由信息：", routeInfo);
        //解析配置信息，将其转化为RouteDefinition对象
        List<RouteDefinition> routeDefinitions = JSONUtil.toList(routeInfo, RouteDefinition.class);
        //删除旧路由表
        for (String routeId : routeIds) {
            routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        }
        routeIds.clear();//清空
        //更新新的路由表
        for (RouteDefinition routeDefinition : routeDefinitions) {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            //记录旧路由id，方便下一次删除
            routeIds.add(routeDefinition.getId());

        }
    }
}
